"""文件存储服务 - 当Redis不可用时，使用文件系统持久化数据"""
import json
import os
from typing import Dict, Any, Optional, List
from pathlib import Path
from datetime import datetime


class FileStorageService:
    """文件存储服务 - 提供类似Redis的接口，但使用文件系统"""
    
    def __init__(self, storage_dir: str = "data"):
        """
        初始化文件存储服务
        
        Args:
            storage_dir: 存储目录，默认为项目根目录下的data文件夹
        """
        try:
            # 获取项目根目录
            project_root = Path(__file__).parent.parent.parent.parent
            self.storage_dir = project_root / storage_dir
            # 快速创建目录（如果已存在不会报错）
            self.storage_dir.mkdir(parents=True, exist_ok=True)
            
            # 创建子目录（快速操作）
            (self.storage_dir / "plans").mkdir(exist_ok=True)
            (self.storage_dir / "records").mkdir(exist_ok=True)
            (self.storage_dir / "users").mkdir(exist_ok=True)
            (self.storage_dir / "sessions").mkdir(exist_ok=True)
        except Exception as e:
            print(f"⚠️ [文件存储] 初始化失败: {e}")
            # 如果初始化失败，使用临时目录
            import tempfile
            self.storage_dir = Path(tempfile.gettempdir()) / "ailawer_data"
            self.storage_dir.mkdir(parents=True, exist_ok=True)
    
    def _get_file_path(self, key: str, subdir: str = "") -> Path:
        """获取文件路径"""
        # 清理key，移除特殊字符
        safe_key = key.replace(":", "_").replace("/", "_")
        if subdir:
            return self.storage_dir / subdir / f"{safe_key}.json"
        return self.storage_dir / f"{safe_key}.json"
    
    def set(self, key: str, value: Any, expire: Optional[int] = None):
        """设置键值对（类似Redis SET）"""
        file_path = self._get_file_path(key)
        
        data = {
            "value": value,
            "created_at": datetime.now().isoformat(),
            "expire_at": None
        }
        
        if expire:
            from datetime import timedelta
            expire_at = datetime.now() + timedelta(seconds=expire)
            data["expire_at"] = expire_at.isoformat()
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"⚠️ [文件存储] 保存失败 {key}: {e}")
    
    def get(self, key: str) -> Optional[Any]:
        """获取值（类似Redis GET）"""
        file_path = self._get_file_path(key)
        
        if not file_path.exists():
            return None
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            # 检查是否过期
            if data.get("expire_at"):
                expire_at = datetime.fromisoformat(data["expire_at"])
                if datetime.now() > expire_at:
                    # 已过期，删除文件
                    file_path.unlink()
                    return None
            
            return data.get("value")
        except Exception as e:
            print(f"⚠️ [文件存储] 读取失败 {key}: {e}")
            return None
    
    def hset(self, hash_key: str, field: str, value: Any):
        """设置哈希字段（类似Redis HSET）"""
        file_path = self._get_file_path(hash_key, "records")
        
        # 读取现有数据
        hash_data = {}
        if file_path.exists():
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    hash_data = json.load(f)
            except:
                hash_data = {}
        
        # 更新字段
        hash_data[field] = value
        hash_data["_updated_at"] = datetime.now().isoformat()
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(hash_data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"⚠️ [文件存储] HSET失败 {hash_key}.{field}: {e}")
    
    def hget(self, hash_key: str, field: str) -> Optional[Any]:
        """获取哈希字段（类似Redis HGET）"""
        file_path = self._get_file_path(hash_key, "records")
        
        if not file_path.exists():
            return None
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                hash_data = json.load(f)
            return hash_data.get(field)
        except Exception as e:
            print(f"⚠️ [文件存储] HGET失败 {hash_key}.{field}: {e}")
            return None
    
    def hgetall(self, hash_key: str) -> Dict[str, Any]:
        """获取所有哈希字段（类似Redis HGETALL）"""
        file_path = self._get_file_path(hash_key, "records")
        
        if not file_path.exists():
            return {}
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                hash_data = json.load(f)
            # 移除内部字段
            return {k: v for k, v in hash_data.items() if not k.startswith("_")}
        except Exception as e:
            print(f"⚠️ [文件存储] HGETALL失败 {hash_key}: {e}")
            return {}
    
    def sadd(self, set_key: str, *members: str):
        """添加集合成员（类似Redis SADD）"""
        file_path = self._get_file_path(set_key, "sessions")
        
        # 读取现有集合
        set_data = set()
        if file_path.exists():
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    set_data = set(data.get("members", []))
            except:
                set_data = set()
        
        # 添加成员
        set_data.update(members)
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump({
                    "members": list(set_data),
                    "_updated_at": datetime.now().isoformat()
                }, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"⚠️ [文件存储] SADD失败 {set_key}: {e}")
    
    def smembers(self, set_key: str) -> set:
        """获取集合所有成员（类似Redis SMEMBERS）"""
        file_path = self._get_file_path(set_key, "sessions")
        
        if not file_path.exists():
            return set()
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                return set(data.get("members", []))
        except Exception as e:
            print(f"⚠️ [文件存储] SMEMBERS失败 {set_key}: {e}")
            return set()
    
    def exists(self, key: str) -> bool:
        """检查键是否存在（类似Redis EXISTS）"""
        file_path = self._get_file_path(key)
        return file_path.exists()
    
    def delete(self, key: str):
        """删除键（类似Redis DEL）"""
        file_path = self._get_file_path(key)
        if file_path.exists():
            try:
                file_path.unlink()
            except Exception as e:
                print(f"⚠️ [文件存储] DELETE失败 {key}: {e}")
    
    def setex(self, key: str, expire: int, value: Any):
        """设置键值对并设置过期时间（类似Redis SETEX）"""
        self.set(key, value, expire=expire)
    
    def expire(self, key: str, expire: int):
        """设置键的过期时间（类似Redis EXPIRE）"""
        file_path = self._get_file_path(key)
        
        if not file_path.exists():
            return
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            from datetime import timedelta
            expire_at = datetime.now() + timedelta(seconds=expire)
            data["expire_at"] = expire_at.isoformat()
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"⚠️ [文件存储] EXPIRE失败 {key}: {e}")


# 单例实例
file_storage_service = FileStorageService()

